单片机中断问题30例及解决办法

您所在的位置:网站首页 uchar code table[11] 单片机中断问题30例及解决办法

单片机中断问题30例及解决办法

#单片机中断问题30例及解决办法| 来源: 网络整理| 查看: 265

博主福利:100G+电子设计学习资源包!

http://mp.weixin.qq.com/mp/homepage?__biz=MzU3OTczMzk5Mg==&hid=7&sn=ad5d5d0f15df84f4a92ebf72f88d4ee8&scene=18#wechat_redirect --------------------------------------------------------------------------------------------------------------------------

1、单片机外中断INT0为下降沿触发,当中断被触发后cpu执行中断程序,若本次中断的程序还未执行完INT0又来了一个相同的下降沿中断信号怎么办?cpu会怎么处理?若是定时器中断呢?串口中断呢?求解释

答:再来一个INT0信号不会执行。相同的优先级不会打断正在执行的中断。 一. 如果是高优先级的中断来了,会打断低优先级的正在执行的中断而执行高优先级的中断。 51单片机的默认(此时的IP寄存器不做设置)中断优先级为: 外部中断0 > 定时/计数器0 > 外部中断1 > 定时/计数器1 > 串行中断; 当同时有几种中断到达时,高优先级中断会先得到服务。 例如:当计数器0中断和外部中断1(优先级 计数器0中断>外部中断1)同时到达时,会进入计时器0的中断服务函数;但是在外部中断1的中断服务函数正在服务的情况下,这时候任何中断都是打断不了它的,包括逻辑优先级比它高的外部中断0计数器0中断。 51单片机的中断优先级控制寄存器IP可以把默认的中断优先级设置为高或低级, 例如默认是外部中断0 > 定时/计数器0 > 外部中断1 > 定时/计数器1 > 串行中断; 现在设为定时1 和串行中断为高优先级 其它为低 ,那么中断0执行时会被定时器1 或串行中断打断,如果设定的两个高优先级定时/计数器1 和串行中断同时响应,会再自然排队,先执行定时1中断再执行串行中断。 2、单片机中断问题,中断3为什么不执行,整个程序有什么不对的地方呢? #include #define uint unsigned int #define uchar unsigned char sbit p1_0=P1^0; sbit p1_1=P1^1; sbit p1_2=P1^2; sbit p1_3=P1^3; sbit p1_4=P1^4; sbit p1_5=P1^5; uchar PWM_T1 = 0; uchar PWM_T2 = 0; uint i,m; void delay(uint z) { for(i=z;i>0;i--) for(m=0;m PWM_T2=pwm_set; } void main(void) { bit flag = 1; uint n; TMOD=0x22; TH0=241; TH1=241; TL0=241; TL1=241; TR0=1; TR1=1; ET0=1; ET1=1; EA=1; P1=0xf0; delay(20); PWM_value_left(7); PWM_value_right(10); delay(100); PWM_value_left(8); PWM_value_right(9); delay(100); PWM_value_left(9); PWM_value_right(8); delay(100); PWM_value_left(10); PWM_value_right(7); } timer0() interrupt 1 using 2 { static uint t ; t++; if(t==10) { t=0; p1_0=1; p1_1=0; } if(PWM_T1==t) P1=P1&0xfc; } timer1() interrupt 3 { static uint t1 ; t1++; if(t1==10) { t1=0; p1_2=1; p1_3=0; } if(PWM_T2==t1) P1=P1&0xf3; } 答:没有主循环, 没有等到中断3 程序运行一次就跑飞了!!! 在 void main(void) { //...你的程序 //在这里加 死循环,等待中断 while(1) { ; } } 而且,中断响应函数里必须要清中断标志位(你的没有)! 3、各位大侠帮我看一下我写的51单片机C程序中断有没有问题,执行中断后不能继续执行主程序,注:P3.2口一直接 注:P3.2口一直接地,程序如下: #include sbit dula=P2^6; sbit wela=P2^7; sbit d0=P1^0; sbit d1=P1^1; sbit d2=P1^2; sbit d3=P1^3; sbit d4=P1^4; sbit d5=P1^5; sbit d6=P1^6; sbit d7=P1^7; #define uchar unsigned char #define uint unsigned int uchar num; uchar code table[]={ 0x3f,0x06,0x5b,0x4f, 0x66,0x6d,0x7d,0x07, 0x7f,0x6f,0x77,0x7c, 0x39,0x5e,0x79,0x71}; void delay(uint z); void main() { EA=1; EX0=1; IT0=0; wela=1; P0=0xc0; wela=0; while(1) { for(num=0;num uint a,b; for(a=z;a>0;a--) for(b=110;b>0;b--); } void exter0() interrupt 0 { uint c; for(c=0;c unsigned char t; while(i--) { for(t=0;t P0=0xfd;//LED1点亮 while((P3|0xf7)==0xff);//等待外部中断1口(P3^3松开) delay(10);//延时去抖动 P0=0xff;//LED1熄灭 } void main() { EA=1;//中断总开关 EX0=1;//外部中断0开 EX1=1;//外部中断1开 /*默认低电平触发*/ while(1);//死循环 防止跑飞 }

 

6、单片机中断问题,下面这段程序不知道为什么只进一次中断,就没有反应了呢? #include // 包含51单片机寄存器定义的头文件 #define uint unsigned int sbit key1=P1^4; sbit key2=P1^5; void delay1ms(uint i) { uchar j; while(i--) { for(j=0;j EA=1; //开总中断 ES=1; //开串口中断 TMOD= 0x21; //定时器1定时方式2,定时器1工作于8位自动重载模式, 用于产生波特率 SCON = 0x50; // 设定串行口工作方式1 允许接收 TH0=(65536-50000)/256; TL0=(65536-50000)%256; TH1= 0xfd; //11.0592M 波特率9600 TL1= 0xfd; PCON =0x00; // 波特率不倍增 TR1= 1; //启动定时器T1 TR0=1; //启动定时器T0 ET0=1; //打开T0中断 } void key() { if(key2==0) P0=0x3f; delay1ms(5000); P0=0xf3; } void mainxh() { while(1) { key(); P0=0x32; } } void keybreak() { P0=0xf1; delay1ms(5000); P0=0x1f; mainxh(); } void main(void) { init(); mainxh(); } void Time0(void) interrupt 1 { TH0=(65536-50000)/256; //定时器T0的高8位重新赋初值 TL0=(65536-50000)%256; //定时器T0的高8位重新赋初值 if(key1==0) keybreak(); } 这个程序上电后P0口显示0x32;按下key2显示0x3f;key1用于中断,每20ms检测是否有按下key1键,有的话,P0口显示0xf1。 答 : ORG 0000H AJMP MAIN ORG 0001H LJMP INT_0 ORG 30H MAIN:MOV SP,#8FH MOV P0,#0FFH MOV P3,#0FFH SETB IT0 SETB EA SETB EX0 LJMP START START: MOV A,#10000000B LOOP: MOV P0,A RLC A LCALL DELAY LCALL DELAY LJMP LOOP LJMP START; 这句是多余的 根本不会执行 INT_0: PUSH ACC ; 由于p中1断中1A被设为10所以5中7断返回后对A移位没有意义,o A一e直为10 ,并不d是只能中断一1次 . 还有,不清楚key1是什么中断,貌似是键盘扫描吧, while(1) { key(); P0=0x32; } 都进入死循环了,所以跳不出来,就一次中断了。 7、新手学习avr单片机ATmage 128 遇到问题,中断程序被忽略问题,找不到原因。 avr studio 4 软件仿真时,编译通过了,单在编译信息栏却看到中断程序被忽略。在软件仿真时也发现中断程序没有执行。不知道问题出在哪里,我用的是avr studio 4 ATmage 128 单片机. 程序如下 #include #include void main() //用的是TC0 溢出中断,来控制八位LED 一秒闪烁 { PORTE = 0xFF; //LED 关 端口高电平位关 DDRE = 0xFF; MCUCR |=(1 TCNT0 = 156; //设初值 j++; if(j EA=1; EX0=1; IT0=0; while(1) { d1=1; dula=1; P0=table[1]; dula=0; P0=0xff; wela=1; P0=0xfe; wela=0; delay(500); dula=1; P0=table[2]; dula=0; P0=0xff; wela=1; P0=0xfd; wela=0; delay(500); dula=1; P0=table[3]; dula=0; P0=0xff; wela=1; P0=0xfb; wela=0; delay(500); dula=1; P0=table[4]; dula=0; P0=0xff; wela=1; P0=0xf7; wela=0; delay(500); dula=1; P0=table[5]; dula=0; P0=0xff; wela=1; P0=0xef; wela=0; delay(500); dula=1; P0=table[6]; dula=0; P0=0xff; wela=1; P0=0xdf; wela=0; delay(500); } } void delay(uint z) { uint x,y; for(x=100;x>0;x--) for(y=z;y>0;y--); } void enter() interrupt 0 { d1=0; } 答: 你这个程序中设置IT0=0,说明是低电平触发,所以只要P3^2口一直是低电平那么主程序停止,所以发光二极管点亮,如果P3^2口变为高电平,主程序继续,发光二极管熄灭。另一种情况是当IT0=1的时候是负跳变触发,就是当P3^2口检测到一个又高电平到低电平的跳变后,触发中断,在中断函数中点亮灯,立即出中断,执行到d1=1时熄灯。看到的现象就是灯闪一下,直到又检测到一个负跳变,灯又闪一下。两种触发方式的现象是不一样的,如果你硬件没问题的话。你可以把中断函数写成d1=!d1试试。 9、在C51单片机中,中断服务程序怎么撤销中断引脚上的低电平? 我用的是,第一个单片机输出低电平到第二个单片机的P3^2,第二个单片机是电平触发方式中断 低电平触发方式:要求低电平保持到CPU实际响应为止,为了避勉CPU再次响应中断,在中断服务程序中应该撤除中断引脚上的低电平。请问,怎么撤销?在中断服务程序中怎么写? 直接写P3^2=1;行吗? 答: 第一个单片机的程序,是谁来编写? 如果也是楼主,那就好办了。 第二个单片机完成了中断的功能,在退出之前,可以向第一个单片机回送一个脉冲; 第一个单片机收到这个脉冲,就应该撤消送到第二个单片机的中断申请信号。 ---- 另外,如果能算出来完成中断的时间,第一个单片机送来的申请信号,就不要超过这个时间,应该及时、自动的撤消申请信号。 第一个单片机送来的申请信号,也不可过短,应该能让对方检测到。 10、程序如下,我想要得到的效果是1秒左边的电动机转动,同时黄灯亮,1秒右边转动,蓝灯亮,以此循环下去,但是这个程序用上去后,左边转》右边转》左边转》之后就一直是左边了,不切换了,谁能帮我解决下问题,感激不尽!! #include sbit m=P2^0; sbit b=P2^6; sbit y=P2^7; unsigned char count; void main() { TMOD=0x01; TH0=(65536-50000)/256; TL0=(65536-50000)%256; TR0=1; ET0=1; EA=1; count=0; m=!0; b=!1; y=!0; while(1) { if(TF0==1) { count++; if(count==20) { m=0; b=1; y=0; } if(count==40) { m=!0; b=!1; y=!0; } TF0=0; TH0=(65536-50000)/256; TL0=(65536-50000)%256; } } } 答案 #include sbit m=P2^0; sbit b=P2^6; sbit y=P2^7; unsigned char count; void main() { TMOD=0x01; TH0=(65536-50000)/256; TL0=(65536-50000)%256; TR0=1; count=0; m=!0; b=!1; y=!0; while(1) { if(TF0==1) { TH0=(65536-50000)/256; TL0=(65536-50000)%256; TF0=0; count++; if(count==20) { m=0; b=1; y=0; } if(count==40) { count=0; //加上这句. m=!0; b=!1; y=!0; } } } }! 用T0定时50ms,溢出20次,溢出40次,分别代表了具体的时间。 溢出40次之后,应该从头开始统计溢出次数,所以,此处应该有count=0;。 楼主原来的程序,缺少count=0;,那么它就会继续增加,直到65536,才自动回到0。 这样,时间,就难以控制了。

 

11、求助关于51单片机外部中断的问题,小弟最近在学单片机,刚做了一个键盘扫描程序。发现如果外部中断为电平触发,程序能正常运行。但如果改为边沿触发,在将键值送给显示重开中断指令为EX0=1后,中断竟然还会被触发一次,这之后,再按键就不能触发中断了。如果将中断程序中关中断语句去掉,按键能被扫描,但引起中断的次数不好说了。请大侠们看看哪出问题了。谢谢 uchar keynum,//定义全局变量按键时的键值 dpnum,//显示值 time1,//延时计数值 topen,//延时计数控制 keyin;//外部中断0向主程序传递有中断标识,有键按下 keydeal;//按键程序调用标志 uchar keytable[4][4]={7,8,9,'/',4,5,6,'*',1,2,3,'-','c',0,'=','+'};//按实际键盘编值 uchar keyboard();//键盘扫描程序,负责键值扫描,判断键释放由主函数完成 void display(uchar,uchar);// 显示子程序, sbit keysign=P3^2;//P3.2为中断0入口,此定义用于程序判断是否真有键按下及键是否释放 void main() {uchar keybiao,keybiao1;//有键按下标志,键放开标志 IE=0x89;//开总中断,外部中断0,定时器中断1 IT0=1;//中断触发方式 PT1=1;//中断优先级 TMOD=0x90;//定时器1工作方式1 TH1=(65536-5000)/256;//定时器初值高8位(定时5ms) TL1=(65536-5000)%256; TR1=1;//开始计时 P2=0xf0;//给键盘列高电平,行低电平 keydeal=0x00;//让键处理初值为0,既未处理 while(1) {if(keyin==1) //可能有键按下 { if(time1>=2)//已延时10ms;计数2次, {if(keysign==0&&keydeal==0) {keynum=keyboard(); keybiao=1; keydeal=1; topen=0;//关延时计数 }//判断是否真有键按下,调用键盘扫描程序 else if(keybiao==0&&time1>=2&&keybiao1==0) {EX0=1; keyin=0; topen=0; }//如果没键按下,重开外部中断0,中断标志清0 } if(keybiao==1&&keysign!=0) {keybiao=0; time1=0; keybiao1=1;//为防止前一次time1的影响而设的标志 topen=1; } if(keybiao1==1&&time1>=2) {keybiao1=0; topen=0; EX0=1; keyin=0;//重开外部中断0,中断标志清0 keydeal=0;//重开键未处理,让程序可调用处理程序 dpnum=keynum;//将键值传给显示 } } } } void display(uchar x,uchar i)//中断控制显示,显示一直持续到下次中断到 uchar keyboard() {uchar con1,con2,i,j; con1=P2|0x0f;//只保留P2口高四位,便于switch switch(con1)//通过cp可得到列为0的位 {case 0x7f:j=3;break;//j为列值 case 0xbf:j=2;break; case 0xdf:j=1;break; case 0xef:j=0;break; } for(i=0;i EN=1; T=0; TMOD=0x01; EA=1; TR0=1; ET0=1; t1=table[T]; TH0=(65536-t1)/256; TL0=(65536-t1)%256; } void timer0() interrupt 1 { TMOD=0x01; EA=1; TR0=1; ET0=1; t1=table[T]; TH0=(65536-t1)/256; TL0=(65536-t1)%256; CLK=~CLK; } 答: T你只付了0值,怎么会变化频率呢?你在主函数里加个T的赋值语句就行了,例如:while(T){T--;delay1s();} 18、单片机中断程序的书写步骤? 答: 标准形式: void 函数名(void)interrupt n using m {函数体语句} n ----中断编号 m-----要使用工作寄存器组号 19、我想知道单片机的蜂鸣器音乐程序中断是如何响应的?从main主程序中如何到中断程序?具体步骤是啥?谢谢! #include sbit speaker = P1^5; unsigned char timer0h, timer0l, time; //-------------------------------------- //单片机晶振采用11.0592MHz // 频率-半周期数据表 高八位 本软件共保存了四个八度的28个频率数据 code unsigned char FREQH[] = { 0xF2, 0xF3, 0xF5, 0xF5, 0xF6, 0xF7, 0xF8, //低音1234567 0xF9, 0xF9, 0xFA, 0xFA, 0xFB, 0xFB, 0xFC, 0xFC,//1,2,3,4,5,6,7,i 0xFC, 0xFD, 0xFD, 0xFD, 0xFD, 0xFE, //高音 234567 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFF}; //超高音 1234567 // 频率-半周期数据表 低八位 code unsigned char FREQL[] = { 0x42, 0xC1, 0x17, 0xB6, 0xD0, 0xD1, 0xB6, //低音1234567 0x21, 0xE1, 0x8C, 0xD8, 0x68, 0xE9, 0x5B, 0x8F, //1,2,3,4,5,6,7,i 0xEE, 0x44, 0x6B, 0xB4, 0xF4, 0x2D, //高音 234567 0x47, 0x77, 0xA2, 0xB6, 0xDA, 0xFA, 0x16}; //超高音 1234567 //-------------------------------------- //世上只有妈妈好数据表 要想演奏不同的乐曲, 只需要修改这个数据表 code unsigned char sszymmh[] = {5,1,1,5,1,1,6,1,2,5,1,2,1,2,2,7,1,4,5,1,1,5,1,1,6,1,2,5,1,2,2,2,2,1,2,4, 5,1,1,5,1,1,5,2,2,3,2,2,1,2,2,7,1,2 }; //-------------------------------------- void t0int() interrupt 1 //T0中断程序,控制发音的音调 { TR0 = 0; //先关闭T0 speaker = !speaker; //输出方波, 发音 TH0 = timer0h; //下次的中断时间, 这个时间, 控制音调高低 TL0 = timer0l; TR0 = 1; //启动T0 } //-------------------------------------- void delay(unsigned char t) //延时程序,控制发音的时间长度 { unsigned char t1; unsigned long t2; for(t1 = 0; t1 < t; t1++) //双重循环, 共延时t个半拍 for(t2 = 0; t2 < 8000; t2++); //延时期间, 可进入T0中断去发音 TR0 = 0; //关闭T0, 停止发音 } //-------------------------------------- void song() //演奏一个音符 { TH0 = timer0h; //控制音调 TL0 = timer0l; TR0 = 1; //启动T0, 由T0输出方波去发音 delay(time); //控制时间长度 } //-------------------------------------- void main(void) { unsigned char k, i; TMOD = 1; //置T0定时工作方式1 ET0 = 1; //开T0中断 IE=0x82; EA = 1; //开CPU中断 while(1) { i = 0; time = 1; while(time) { k = sszymmh[i] + 7 * sszymmh[i + 1] - 1; //第i个是音符, 第i+1个是第几个八度 timer0h = FREQH[k]; //从数据表中读出频率数值 timer0l = FREQL[k]; //实际上, 是定时的时间长度 time = ssz ymmh[i + 2]; //读出时间长度数值 i += 3; song(); //发出一个音符 } } } 答: 你看main()函数就行了,首先进行k、i的定义,然后是定义中断的类型(程序中用的是定时器中断),这个定时器有点特殊,它的作用是定义频率的,频率间隔小则声调高,反之声调低。这个频率就是时间的倒数呗,所以TH的值越大,声调越高;TL的值越小,声调越低。接着往下走,while(1) 就是等待中断的意思,这个程序中的定时器中断没有设置初值,所以中断几乎没有等待,时时触发(要是有等待时间,音乐不就连不上了么)。综上:这个定时器中断完成两个任务:1、使单片机时时触发(等待时间几乎为0);2、控制了音符的演奏频率。 再往下 while(time) 的循环就是为演奏的音符赋值的操作了。 20、单片机中断该什么时候进如? 答: 中断看是外部中断、定时器还是串行口中断了。 如果是外部中断,就是p3.2、p3.3检测到这两个口电平变化时(假设这两个口接上按键,那么当按键按下时表明产生中断),然后跳到中断程序执行。 如果是定时器中断的话,有个中断标志位TFx(x表示0或者1),比如说你设置一个1S的定时器程序,你以50ms为基准,20次产生1s的时间,然后当50ms一过,标志位就产生变化,进入定时器中断程序执行! 串行口中断也是一样有一个标志位,接受或者发送数据满了以后,标志位就发生变化,然后进入中断执行!

 

21、PIC单片机AD中断什么时候开启,对AD中断应该怎样理解。 答: AD模数转换,是把模拟电压数值采样进来,然后转换成数字信号。这一采样和转换是需要时间的。并不是一开AD就能读到数字信号数据。 一般来说其时间都只有几微秒到几百微秒(根据设置不同而定)。如果单片机没有其他工作的时候,可以用循环等待的方式等AD转换结束(转换结束后DONE位会被置位)。但如果你的单片机还有其他工作,那就没必要在等待它上面花费时间。可以开AD操作后,继续执行其他程序。而转换结束后,AD中断可以暂时断开现有炒作,而把AD数据读进来。这就是AD中断的作用。 22\51单片机的五个中断分别在什么时候(什么情况)执行里面的程序! 答: 外部中断0 :P3.2口有低电平(IT0=0)/ 下降沿(IT0=1)。 外部中断1 :P3.3口有低电平(IT1=0)/ 下降沿(IT1=1)。 定时器0中断:当定时器0计数到FFFF溢出时 定时器1中断:当定时器1计数到FFFF溢出时 串口中断:串口接收到一帧。或发送完一帧数据都会产生中断。 你网上找一下TCON和SCON。什么条件让中断标志位的值改变。 那么就会进入中断服务程序去。 23、51单片机,如果中断函数比较长,执行到一半又触发了这个中断,程序会停止从头执行,还是执行结束后响应中 答: 51单片机中,中断分高低两个优先级,高优先级的中断能打断低优先级的中断。 但同级中断是不能打断同级中断的!无论该中断函数有多长,在执行到一半这个中断又发生了,还是要等到该中断函数执行完毕,并再执行了一条主程序指令后才会再次进入该中断。 不过,若楼主恰好在这个低优先级中断服务程序中修改了该中断为高优先级,那么如果该中断函数比较长,执行到一半又触发了这个中断,则该中断函数就会被重新从头开始执行(中断嵌套)。这是因为除串口中断以外的其他中断,在 CPU 响应该中断,程序转入该中断函数前就已经将该中断的中断标志清零了。 另外,51的串口中断比较特别,因为需要软件清除串口中断标志,所以只要在未清串口中断标志前,是不会发生上述这样的中断嵌套的。 24、求51单片机程序,两个计数器,主要是中断函数的函数名以及初始化设置 答: void into_into() interrupt 1 定时器0中断入口函数 { 。。。。中断服务程序。。。。 TH0=0;// TL0=0;// 重新给T0赐值 } void into_into() interrupt 3 定时器1中断入口函数 { 。。。。中断服务程序。。。。 TH1=0;// TL1=0;// 重新给T1赐值 } void to_to() { TMOD=0x11; //顶时器T0和T1工作方式1 TH0=0;// TL0=0;// T0赐初值 TH1=0;// TL1=0// T1赐初值 TR0=1;// 开始记数 ET0=1;// 允许T0中断 TR1=1;// 开始记数 ET1=1;// 允许T1中断 EA=1; // 打开总中断 } void main() { INIT_T0(); //定时器中断初始化 while(1) { ........... } 25、请教一个单片机中断的问题:比如来了一个脉冲,开始中断,但中断里的程序执行到一半时,又来了一个脉冲,请问这时中断里的程序是从头开始呢还是继续呢? 我的意思是程序就一个中断A,来了一个脉冲,A执行,A执行到一半时,又来了一个脉冲,通知A执行。这时A是从头执行还是先不理会呢? 答: 需要具体情况具体分析,因为不同的单片机在中断机制上有细微的差别,需要查他的资料。 一般来说,一个中断源请求中断,对CPU来说,是一次性的做了一个“中断挂号”。假如当时因条件不满足(例如CPU正在“关中断”,即没有打开“中断允许”),而没有响应中断,则挂号信息还在,这样,将来一旦打开了中断允许,仍然会响应,只是晚了一点而已。 而中断响应以后,必须有办法把这个“中断挂号”消除掉。有的CPU的功能是:只要响应了这个中断,挂号就自动消除了。也有的CPU不能自动清除挂号,必须在中断服务程序中编入“清除中断挂号”的操作,否则,一旦打开了中断允许,它又会重复发生中断。 现在的大多数单片机里,中断控制器和CPU是在同一个芯片中,它可以做到自动消除中断挂号。而过去许多种CPU,所配用的中断控制器是另外一个芯片,自然就无法自动消除了。 也有的CPU中有另外一种“不挂号”的中断请求。它必须由外界(发出中断请求的那个设备)来保持一直不停申请,等到响应中断的时候,再设法(例如,在中断服务程序中发出一个输出信号)通知那个设备撤销申请。 大多数的CPU中,一旦响应中断进入了服务程序,就把“中断允许”关掉了。故此时如果又有下一个中断请求来了,不能立即响应,只能挂一个号,等以后“开中断”时才能再响应。如果程序员希望能够“嵌套中断”(即在一次中断服务程序的执行中途又进入了另一个中断服务程序),就需要在服务程序内编入“开中断”的操作。 “嵌套中断”原则上允许“自己嵌套自己”,也就是说,一次中断服务程序的执行中途又被打断并进入了和自己一样的中断服务程序,并从头到尾执行一遍,结束后返回到先前打断的那一点,并继续执行后半截服务程序。这种情况会产生什么效果,是需要程序员自己考虑的。 也有的CPU具有“优先次序”机制,可以在某一级的中断服务程序里禁止优先级不比自己高的其他中断来打断自己。同时,也提供给程序员有“放弃优先权”以及“修改优先级”的灵活性。 而被优先机制暂时“屏蔽”的那些较低优先级的中断申请,同样挂号仍在,以后高优先级的中断结束以后,还能响应。 不过需要注意,大多数的CPU中,“中断挂号”是只能挂一个的。也就是说,在前一次的中断申请所挂的号还没有被清除以前,又来了下一个中断申请,那么,第二个挂号是挂不上的。 不过某些处理器中,中断挂号可能分成几个层次:CPU里面是一层,外围针对各个具体的设备,还有另外一级“预备挂号”,那就比较复杂了。 另外多说几句:上面已经说,程序员可以自己决定你的中断服务程序允许还是不允许“嵌套”。 如果不允许,您可以采用关中断的办法,或者利用优先机制,来屏蔽同一中断源的第二个中断请求。 这样,第二个中断就不会被响应。但它仍可以挂上一个号(只要它发生在上一个中断挂号已经被清除掉以后的时间)。然后,中断服务程序结束时,一般都会开中断并释放优先级屏蔽。然后,第二个中断请求就会被响应,于是再一次执行中断服务程序。 如果允许“嵌套”,那就会如我上面所说: 一次中断服务程序的执行中途又被打断并进入了和自己一样的中断服务程序,并从头到尾执行一遍,结束后返回到先前打断的那一点,并继续执行后半截服务程序。

 

26、我用51单片机定时/计数器1计数为什么不计数?想让它记数产生中断让蜂鸣器响。 sbit fengming=P1^6; void main() { TMOD=0x50; EA=1; ET1=1; TH1=0xff;//来一次中断记一次数 TL1=0xff; TR1=1; } void time1(void) interrupt 3 { fengming=0; } 答: 不知道是你在网页上打错了,还是怎么回事。 void time1(void) interrupt 3-------》void timer1(void) interrupt 3 主程序最后,要加个死循环:while(1){}; 还有,你在这用了方式1,这个方式在你进中断后,TH1和TL1会变成0000H。你不对他重新赋值,你要等FFFFH次计数,才会进中断。 27\MCS-51 单片机定时器/计数器1的中断入口地址是: 一共有四个A. 0003H B. 000BH C. 0013H D. 001BH,到底是是哪一个? \答:答案是D.1BH 因为: 外中断0——03h 定时器0——0bh 外中断1——13h 定时器1——1bh 串口———23h 请背熟 28、我看很多程序都是主程序进入while(1),就死在while(1)里了,然后等待外中断。那么现在的问题是我想让它进入外中断完事后,跳过while(1),执行下边的程序,该怎么办? while里边用break吗?不知道好使不好使,还有标志位我看是硬件自动清零,查询标志应该不能用吧,那该怎么办呢? 答: 结束while(1)语句最好的方法就是使用break来跳出死循环,关键就是选择合适的flag(标志位),如果说中断标志位是硬件自动清零的话,那么楼主不妨在中断服务子程序中自己加入一个标志位:如果用汇编语言的话,PSW中的F0位就可以很好的使用;如果用C的话,就可以随便定义一个位变量,如bit a=0;。也就是说,楼主需要在程序中定义一个位变量a,在中断服务子程序中将a置1,退出中断后查询a是否为1,例如:if(a) {a=0;break;}这样就跳出了while语句了。 比方说,如果楼主想写一个等待按键按下中断的程序,就可以用while(!a);而不用while(1)语句了。 29、我用外部中断1,中断一次显示下一个数,数码管显示没问题。但是我用P3-3口用导线连接,接触一次地线,松开一次,这时候数码管显示会乱跳,有时候加两次数,有时候加好多次数,反正就是不稳定。假如p3-3口通过按键接地的话,按一次按键一般情况会加一次数,但有时候也是不稳定,可能中断好几次。 程序如下: #include #define uint unsigned int #define uchar unsigned char uchar code table[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90}; uchar times; uchar i=0; void delay(uint z) { uint x,y; for(x=z;x>0;x--) for(y=112;y>0;y--); } void main() { EA=1; EX1=1; IT1=1; while(1) { P1=table[i]; P2=0x00; } } void into() interrupt 2 { delay(1000); i++; if(i==10) i=1; } 答: 是抖动的问题。 应该采取消抖措施,硬件、软件方法皆可。 ---- 楼主在中断函数中,延时,时间看来很是不短! 但是延时后,并没有检测按键是否还在按下,这就不能算是软件消抖。 30、 (1) 为什么单片机有两个外部中断0允许位?有什么作用? (2)在51内核单片机中,当允许响应外部中断0的中断请求时,其特殊功能寄存器ie中的位必须为1 es exo ea et0? 答: (1)两个中断是因为一般的单片机有两个中断源,可以实现两级中断嵌套,在实现复杂功能上两级中断嵌套很有用。 (2) EA--总中断允许位,必须为1 ES--串行中断允许位,不必开,为0 EX0--外部中断0允许位,应为1 ET0--定时计数溢出中断允许位,不必开,为0

 

 



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3